package com.dd.census.tools.excel;

import java.beans.PropertyDescriptor;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.util.StringUtils;

import com.dd.census.tools.Utils;

public class ExcelExport {

	public <E> void createExcel(OutputStream out, Integer[] arr, List<E> list, Class<E> clazz) throws Exception {
		createExcel(out, arr,list, clazz, "sheet", null);
	}

	public <E> void createExcel(OutputStream out, Integer[] arr, List<E> list, Class<E> clazz, String sheetName) throws Exception {
		createExcel(out, arr,list, clazz, sheetName, null);
	}

	@SuppressWarnings("static-access")
	public <E> void createExcel(OutputStream out,Integer[] arr, List<E> list, Class<E> clazz, String sheetName, ExcelExportCallback excelExportCallback) throws Exception {

		// 创建工作表
		Workbook wb = new XSSFWorkbook();
		// 创建sheet页
		Sheet sheet = wb.createSheet(sheetName);
		sheet.setDefaultColumnWidth((short) 20);

		// 回调自定义方法
		if (excelExportCallback != null)
			excelExportCallback.call(sheet);

		// 定义单元格字体
		Font font = wb.createFont();
		font.setFontName("Courier New");

		// 表头单元格样式
		CellStyle styleHeader = wb.createCellStyle();
		styleHeader.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
		styleHeader.setFillPattern(CellStyle.SOLID_FOREGROUND);
		styleHeader.setAlignment(XSSFCellStyle.ALIGN_CENTER);
		styleHeader.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);
		styleHeader.setBorderBottom(XSSFCellStyle.BORDER_THIN);// 边框
		styleHeader.setBorderLeft(XSSFCellStyle.BORDER_THIN);// 边框
		styleHeader.setBorderRight(XSSFCellStyle.BORDER_THIN);// 边框
		styleHeader.setBorderTop(XSSFCellStyle.BORDER_THIN);// 边框

		// 设置字体
		styleHeader.setFont(font);

		// 单元格样式
		CellStyle style = wb.createCellStyle();
		// 设置字体
		style.setFont(font);

		// 创建表头
		Row rowHeader = sheet.createRow(0);
		rowHeader.setHeight((short) 400);
		// 所有字段
		Field[] fsHeader = clazz.getDeclaredFields();
		for (Field f : fsHeader) {
			
			// 包含注解的字段
			ExcelField ef = f.getAnnotation(ExcelField.class);
			if (ef != null) {
				if(!Arrays.asList(arr).contains(ef.index())){
					// 注解所在位置
					Cell cellHeader = rowHeader.createCell(ef.index());
					// 表头显示样式
					cellHeader.setCellStyle(styleHeader);
					// 注解中的name值
					cellHeader.setCellValue(ef.name());
				}
				if(ef.isList()){
					// 当前行数据
					E e = list.get(0);
					// 方法名首字母大写
					String n0 = f.getName().substring(0, 1).toUpperCase();
					// 方法名其他部分
					String n1 = f.getName().substring(1);
					// 获取字段get方法
					Method m = clazz.getMethod("get" + n0 + n1, new Class[] {});
					// 执行字段get方法
					Object obj = m.invoke(e, new Object[] {});
					int in = 0 ;
					if (obj instanceof ArrayList<?>) {
						in = ef.index();
				        for (Object o : (List<?>) obj) {
							// 注解所在位置
							Cell cellHeader = rowHeader.createCell(in);
							// 表头显示样式
							cellHeader.setCellStyle(styleHeader);
							// 注解中的name值
							cellHeader.setCellValue( this.method(o,ef.title()).toString());
							in++;
				        }
				    }

					
				}
			}
		}

		// 所有数据
		for (int i = 0; i < list.size(); i++) {
			// 当前行数据
			E e = list.get(i);
			// 创建当前行
			Row row = sheet.createRow(i + 1);
			// 所有字段
			Field[] fs = clazz.getDeclaredFields();
			for (Field f : fs) {
				// 包含注解的字段
				ExcelField ef = f.getAnnotation(ExcelField.class);
				if (ef != null) {
					if(!Arrays.asList(arr).contains(ef.index())){
						// 根据注解索引在行中创建列
						Cell cell = row.createCell(ef.index());
						// 表头显示样式
						cell.setCellStyle(style);
						// 方法名首字母大写
						String n0 = f.getName().substring(0, 1).toUpperCase();
						// 方法名其他部分
						String n1 = f.getName().substring(1);
						// 获取字段get方法
						Method m = clazz.getMethod("get" + n0 + n1, new Class[] {});
						// 执行字段get方法
						Object obj = m.invoke(e, new Object[] {});
						// 获取字段类型
						Class<?> fieldType = f.getType();
						if (fieldType == String.class) {
							// 字符串
							cell.setCellValue(StringUtils.isEmpty(obj)?"": obj.toString());
						} else if (Integer.class == fieldType) {
							// 整数型
							cell.setCellValue(StringUtils.isEmpty(obj)?0 : (Integer) obj);
						} else if (Double.class == fieldType) {
							// 浮点型
							cell.setCellValue((Double) obj);
						} else if (Date.class == fieldType) {
							// 日期型
							Date date = (Date) obj;
							// 单元格展示的样式
							CellStyle cs = wb.createCellStyle();
							DataFormat df = wb.createDataFormat();
							cs.setDataFormat(df.getFormat("yyyy/MM/dd"));
							cs.setFont(font);
							cell.setCellStyle(cs);
							// 丢弃时分秒部分
							SimpleDateFormat sf = new SimpleDateFormat("yyyy/MM/dd");
							if(null == date) {
								cell.setCellValue("");
							}else {
								cell.setCellValue(sf.parse(sf.format(date)));
							}
						}
						if(ef.isList()){
							@SuppressWarnings("unused")
							int in = 0 ;
							if (obj instanceof ArrayList<?>) {
								in = ef.index();
								List<?> a = (List<?>) obj;
								for (int j = 0; j < a.size(); j++) {
									cell = row.createCell(in);
						        	if(StringUtils.isEmpty(a.get(j)) ||StringUtils.isEmpty(this.method(a.get(j),ef.name_t()))) {
						        		cell.setCellValue("");
						        	}else {
						        		if(j == 0 ) {
						        			// 显示时间
											Date date = (Date) this.method(a.get(j),ef.name_t());
											SimpleDateFormat sf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.S");
											cell.setCellValue(sf.format(date));
						        		}else {
											Date dateEnd = (Date) this.method(a.get(j),ef.name_t());
											Date dateNow = (Date) this.method(a.get(j-1),ef.name_t());
											if(dateEnd == null) {
												cell.setCellValue("");
											}else {
												if(dateNow == null) {
													for (int k = 1; k < a.size(); k++) {
														dateNow = (Date) this.method(a.get(j-k),ef.name_t());
														if(dateNow != null) {
															break;
														}
													}
												}
												cell.setCellValue(Utils.getDatePoor(dateEnd,dateNow));
											}
						        		}
						        	}
									in++;
								}
						    }
						}
					}
				}
			}
		}
		wb.write(out);
		out.close();
	}
	
	/**
	 * 通过对象和具体的字段名字获得字段的值
	 * @param obj 目的对象
	 * @param filed 字段名
	 * @return 通过字段名得到字段值
	 */
	public static Object method(Object obj,String filed)   {
	   try {
		   @SuppressWarnings("rawtypes")
		   Class clazz = obj.getClass();
		   PropertyDescriptor pd = new PropertyDescriptor(filed,clazz);
		   Method getMethod = pd.getReadMethod();//获得get方法
	       Object o = getMethod.invoke(obj);//执行get方法返回一个Object
	       return o;
	   }catch (Exception e) {
		   e.printStackTrace();
		   return null;
	   } 
	 }

}
